package com.forgenet.testclient.panel;

import com.forgenet.testclient.ClientMain;
import com.sparrow.common.util.PackageUtil;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.lang.reflect.Field;
import java.util.List;
import java.util.*;

public class TestMsgPanel extends JPanel {
    private final JComboBox<String> classComboBox;
    private final JTextField manualClassField;
    private JPanel fieldsPanel;
    JScrollPane scrollPane;
    public static JTextArea outputArea;

    private final Map<Field, JComponent> fieldInputs = new HashMap<>();

    private static final Set<Class<?>> excludes = new HashSet<>();
    static {
//        excludes.add(ReqBackPackOrganize.class);
    }

    public TestMsgPanel() {
        setLayout(new BorderLayout(10, 10));

        JPanel topPanel = new JPanel(new BorderLayout(5, 5));
        topPanel.setBorder(new EmptyBorder(10, 10, 0, 10));

        List<String> classes = new ArrayList<>();
        PackageUtil.scanClass(new String[]{"com.forgenet.message"}, clazz -> {
            if (excludes.contains(clazz)) {
                return;
            }
            if (!clazz.getName().contains("$")) {
                if (clazz.getSimpleName().startsWith("Req")) {
                    classes.add(clazz.getName());
                }
            }
        }, null);

        String[] array = classes.toArray(new String[0]);

        // 默认选中第一个类
        classComboBox = new JComboBox<>(array);
        classComboBox.setEditable(false);
        classComboBox.addActionListener(this::onClassSelected);

        // 手动输入框
        manualClassField = new JTextField(array.length > 0 ? array[0] : "");

        JButton loadButton = new JButton("加载Class");
        loadButton.addActionListener(this::onLoadClass);

        JPanel comboPanel = new JPanel(new BorderLayout(5, 5));
        comboPanel.add(new JLabel("Select Class:"), BorderLayout.WEST);
        comboPanel.add(classComboBox, BorderLayout.CENTER);

        JPanel inputPanel = new JPanel(new GridLayout(2, 1, 5, 5));
        inputPanel.add(comboPanel);

        topPanel.add(inputPanel, BorderLayout.CENTER);
        topPanel.add(loadButton, BorderLayout.EAST);

        add(topPanel, BorderLayout.NORTH);

        // 初始化字段面板
        fieldsPanel = new JPanel();
        fieldsPanel.setPreferredSize(new Dimension(500, 200));  // 给它一个初始的首选大小，避免没有字段时显示异常
        fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.Y_AXIS));
        scrollPane = new JScrollPane(fieldsPanel);
        add(scrollPane, BorderLayout.CENTER);

        // 发送按钮
        JButton sendButton = new JButton("发送");
        sendButton.addActionListener(this::onSendPacket);
        JPanel bottomPanel = new JPanel(new BorderLayout());
        bottomPanel.setBorder(new EmptyBorder(0, 10, 10, 10));
        bottomPanel.add(sendButton, BorderLayout.NORTH);

        outputArea = new JTextArea(6, 40);
        outputArea.setEditable(false);
        JScrollPane outputScroll = new JScrollPane(outputArea);
        bottomPanel.add(outputScroll, BorderLayout.CENTER);

        add(bottomPanel, BorderLayout.SOUTH);

        // 加载默认类
        if (array.length > 0) {
            loadClass(array[0]);
        }
    }

    private void addNewFieldPanel() {
        fieldsPanel = new JPanel();
        fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.Y_AXIS));
        scrollPane = new JScrollPane(fieldsPanel);
        add(scrollPane, BorderLayout.CENTER);
    }

    private void onClassSelected(ActionEvent e) {
        String selectedClass = (String) classComboBox.getSelectedItem();
        if (selectedClass != null) {
            manualClassField.setText(selectedClass);
        }
    }

    private void onLoadClass(ActionEvent e) {
        String className = manualClassField.getText().trim();
        loadClass(className);
    }

    private void loadClass(String className) {
//        addNewFieldPanel();
        fieldsPanel.removeAll();  // 清空原有组件
        fieldInputs.clear();  // 清空映射

        try {
            Class<?> clazz = Class.forName(className);
            Field[] fields = clazz.getDeclaredFields();  // 获取所有字段

            // 为每个字段创建组件并添加到 fieldsPanel
            for (Field field : fields) {
                JPanel fieldPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
                fieldPanel.add(new JLabel(field.getName() + " (" + field.getType().getSimpleName() + "):"));

                JComponent inputComponent = createInputForField(field);
                fieldInputs.put(field, inputComponent);

                fieldPanel.add(inputComponent);
                fieldsPanel.add(fieldPanel);
            }

            // 刷新滚动面板
            scrollPane.updateUI();
            scrollPane.revalidate();  // 确保滚动面板刷新
            scrollPane.repaint();

            // 更新显示
            fieldsPanel.updateUI();
            fieldsPanel.revalidate();
            fieldsPanel.repaint();

            revalidate();
            outputArea.setText("Loaded class: " + className);

        } catch (ClassNotFoundException ex) {
            JOptionPane.showMessageDialog(this, "Class not found: " + className,
                    "Error", JOptionPane.ERROR_MESSAGE);
            ex.printStackTrace(); // 打印堆栈信息，便于调试
            outputArea.setText("Error: Class not found");
        } catch (Exception ex) {
            // 捕获其他可能的异常
            JOptionPane.showMessageDialog(this, "Error loading class: " + ex.getMessage(),
                    "Error", JOptionPane.ERROR_MESSAGE);
            ex.printStackTrace(); // 打印堆栈信息
            outputArea.setText("Error: " + ex.getMessage());
        }
    }


    public static void setText(String str) {
        if (outputArea != null) {
            outputArea.setText(str);
        }
    }

    private JComponent createInputForField(Field field) {
        Class<?> type = field.getType();

        if (type == boolean.class || type == Boolean.class) {
            return new JCheckBox();
        } else if (type == int.class || type == Integer.class
                || type == long.class || type == Long.class
                || type == float.class || type == Float.class
                || type == double.class || type == Double.class
                || type == short.class || type == Short.class
                || type == byte.class || type == Byte.class) {
            JTextField tf = new JTextField(15);
            tf.setText("0");
            return tf;
        } else if (type == String.class) {
            JTextField tf = new JTextField(20);
            return tf;
        } else {
            JTextField tf = new JTextField(20);
            tf.setEnabled(false);
            tf.setText("Unsupported Type");
            return tf;
        }
    }

    private void onSendPacket(ActionEvent e) {
        String className = manualClassField.getText().trim();
        try {
            Class<?> clazz = Class.forName(className);
            Object instance = clazz.getDeclaredConstructor().newInstance();

            for (Map.Entry<Field, JComponent> entry : fieldInputs.entrySet()) {
                Field field = entry.getKey();
                JComponent comp = entry.getValue();
                field.setAccessible(true);

                Object value = null;
                Class<?> type = field.getType();

                if (comp instanceof JCheckBox) {
                    value = ((JCheckBox) comp).isSelected();
                } else if (comp instanceof JTextField) {
                    String text = ((JTextField) comp).getText();
                    if (type == String.class) {
                        value = text;
                    } else if (type == int.class || type == Integer.class) {
                        value = Integer.parseInt(text);
                    } else if (type == long.class || type == Long.class) {
                        value = Long.parseLong(text);
                    } else if (type == float.class || type == Float.class) {
                        value = Float.parseFloat(text);
                    } else if (type == double.class || type == Double.class) {
                        value = Double.parseDouble(text);
                    } else if (type == short.class || type == Short.class) {
                        value = Short.parseShort(text);
                    } else if (type == byte.class || type == Byte.class) {
                        value = Byte.parseByte(text);
                    } else {
                        continue;
                    }
                }
                field.set(instance, value);
            }
            ClientMain.channel.writeAndFlush(instance);
            String json = com.sparrow.common.util.JsonUtil.toJSON(instance);
            outputArea.setText("Packet JSON:\n" + json);

        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "Error: " + ex.getMessage(),
                    "Error", JOptionPane.ERROR_MESSAGE);
            ex.printStackTrace();
        }
    }
}

